﻿using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SM
{
    public class SM4Util
    {
        /// <summary>
        /// 加密密钥
        /// </summary>
        public static string secretKey = ""; // 长度必须为16字节
        /// <summary>
        /// 偏移量
        /// </summary>
        public static string iv = "";
        /// <summary>
        /// hex
        /// </summary>
        public static bool hexString = false;

        /// <summary>
        /// ECB加密
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static  string Encrypt_ECB(string plainText)
        {
            var ctx = new SM4_Context
            {
                isPadding = true,
                mode = SM4.SM4_ENCRYPT
            };

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.ASCII.GetBytes(secretKey);
            }

            var sm4 = new SM4();
            sm4.Sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4_crypt_ecb(ctx, Encoding.ASCII.GetBytes(plainText));

            string cipherText = Encoding.ASCII.GetString(Hex.Encode(encrypted));
            return cipherText;
        }
        public static string Encrypt_ECB(string pk ,string plainText)
        {
            var ctx = new SM4_Context
            {
                isPadding = true,
                mode = SM4.SM4_ENCRYPT
            };

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(pk);
            }
            else
            {
                keyBytes = Encoding.ASCII.GetBytes(pk);
            }

            var sm4 = new SM4();
            sm4.Sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4_crypt_ecb(ctx, Encoding.ASCII.GetBytes(plainText));

            string cipherText = Encoding.ASCII.GetString(Hex.Encode(encrypted));
            return cipherText;
        }
        /// <summary>
        /// ECB加密
        /// </summary>
        /// <param name="plainBytes"></param>
        /// <param name="keyBytes"></param>
        /// <returns></returns>
        public static byte[] Encrypt_ECB(byte[] keyBytes,byte[] plainBytes)
        {
            var ctx = new SM4_Context
            {
                isPadding = false,
                mode = SM4.SM4_ENCRYPT
            };

            var sm4 = new SM4();
            sm4.Sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4_crypt_ecb(ctx, plainBytes);
            return encrypted;

            //return Hex.Encode(encrypted);
        }
        /// <summary>
        /// ECB解密
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns></returns>
        public static string Decrypt_ECB(string cipherText)
        {
            var ctx = new SM4_Context
            {
                isPadding = true,
                mode = SM4.SM4_DECRYPT
            };

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.ASCII.GetBytes(secretKey);
            }

            var sm4 = new SM4();
            sm4.Sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.Sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
            return Encoding.ASCII.GetString(decrypted);
        }
        /// <summary>
        /// CBC加密
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public string Encrypt_CBC(string plainText)
        {
            var ctx = new SM4_Context
            {
                isPadding = true,
                mode = SM4.SM4_ENCRYPT
            };

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.ASCII.GetBytes(secretKey);
                ivBytes = Encoding.ASCII.GetBytes(iv);
            }

            var sm4 = new SM4();
            sm4.Sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4_crypt_cbc(ctx, ivBytes, Encoding.ASCII.GetBytes(plainText));

            string cipherText = Encoding.ASCII.GetString(Hex.Encode(encrypted));
            return cipherText;
        }
        /// <summary>
        /// CBC解密
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns></returns>
        public string Decrypt_CBC(string cipherText)
        {
            var ctx = new SM4_Context
            {
                isPadding = true,
                mode = SM4.SM4_DECRYPT
            };

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.ASCII.GetBytes(secretKey);
                ivBytes = Encoding.ASCII.GetBytes(iv);
            }

            var sm4 = new SM4();
            sm4.Sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.Sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
            return Encoding.ASCII.GetString(decrypted);
        }
    }
}
